package component.controls
{
	import component.controls.ui.ArrowButton;
	import component.controls.ui.Component;
	import component.controls.ui.ThumbButton;
	import component.global.ComponentSetting;
	import component.global.manager.EventMgr;
	import component.global.manager.StageManager;
	import component.global.utils.DisplayUtils;
	import component.global.utils.GraphicsUtils;
	import component.global.utils.ObjectUtil;
	import component.global.utils.PositionUtils;
	
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	public class ScrollBar extends Component
	{
		public function ScrollBar($height:int = ComponentSetting.SCROLL_BAR_DEFAULT_HEIGHT)
		{
			_height = $height;
			super();
		}
		
		protected var _decreaseBtn:ArrowButton;
		protected var _increaseBtn:ArrowButton;
		protected var _thumbBtn:ThumbButton;
		protected var _scrollUnit:int = 4;
		protected var _viewPort:Shape;
		protected var _scrollPos:int;
		protected var _originalPos:int;
		protected var _targetDisplay:DisplayObject;
		protected var _mouseY:int;
		protected var _wheelArea:Rectangle;
		protected var _delayTime:int = 200;
		protected var _repeatTime:int = 100;
		protected var _timerScrollUnit:int;
		protected var _btnTimer:Timer;
		protected var _isDraging:Boolean;
		
		public function get scrollPos():int
		{
			return _scrollPos;
		}

		public function set scrollPos(value:int):void
		{
			_scrollPos = value;
		}

		override protected function init():void{
			super.init();
			_btnTimer = new Timer(_repeatTime);
			_background = GraphicsUtils.createRectangle(ComponentSetting.SCROLL_BAR_DEFAULT_WIDTH,_height);
			_decreaseBtn = new ArrowButton(_background.width,_background.width);
			_increaseBtn = new ArrowButton(_background.width,_background.width);
			_thumbBtn = new ThumbButton(_background.width,_background.width);
			
			_background.filters = _filters[0];
			_increaseBtn.x = _increaseBtn.width;
			_increaseBtn.y = _background.height;
			_increaseBtn.rotation = 180;
			
			EventMgr.Instance.addEvent(_thumbBtn, [MouseEvent.MOUSE_DOWN,MouseEvent.ROLL_OVER],[__onThumbMouseDown,__onMouseUpHandler]);
			EventMgr.Instance.addEvent(_btnTimer,[TimerEvent.TIMER],[__onBtnTimerTick]);
			EventMgr.Instance.addEvent(StageManager.Instance.stage,[MouseEvent.MOUSE_UP],[__onMouseUpHandler]);
			EventMgr.Instance.addEvent(this,[MouseEvent.MOUSE_DOWN,MouseEvent.MOUSE_UP],[__onBtnDownHandler,__onMouseUpHandler]);
			EventMgr.Instance.addEvent(_decreaseBtn,[MouseEvent.MOUSE_DOWN,MouseEvent.MOUSE_UP,MouseEvent.ROLL_OUT],[__onBtnDownHandler,__onMouseUpHandler,__onMouseUpHandler]);
			EventMgr.Instance.addEvent(_increaseBtn,[MouseEvent.MOUSE_DOWN,MouseEvent.MOUSE_UP,MouseEvent.ROLL_OUT],[__onBtnDownHandler,__onMouseUpHandler,__onMouseUpHandler]);
			
			DisplayUtils.addDisplayObject(this, _background,_decreaseBtn, _increaseBtn);
		}
		
		public function set targetDisplay(displayObject:DisplayObject):void{
			if(_targetDisplay == displayObject){
				scrollTo(0);
				return;
			}
			_targetDisplay = displayObject;
			if(_viewPort == null){
				_viewPort = GraphicsUtils.createRectangle(_targetDisplay.width, height);
			}
			PositionUtils.setPos(_viewPort,_targetDisplay);
			_wheelArea = new Rectangle(-_targetDisplay.width,0, width , height);
			EventMgr.Instance.addEvent(_targetDisplay as InteractiveObject,[Event.ADDED_TO_STAGE,Box.ON_RESIZE],[__onTargetAdded, __onTargetResize]);
			__onTargetAdded();
		}
		
		protected function __onTargetAdded(e:Event = null):void{
			DisplayUtils.addDisplayObject(_targetDisplay.parent,this,_viewPort);
			this.x = _targetDisplay.width + _targetDisplay.x;
			_targetDisplay.mask = _viewPort;
			EventMgr.Instance.addEvent(StageManager.Instance.stage,[MouseEvent.MOUSE_WHEEL],[__onMouseWheel]);
			_originalPos = _targetDisplay.y;
			updateThumb();
		}
		
		private function __onTargetResize(e:Event):void{
			updateThumb();
		}
		
		public function updateThumb():void{
			if(_targetDisplay && _viewPort && _targetDisplay.height>_viewPort.height){
				DisplayUtils.addDisplayObject(this,_thumbBtn);
				_thumbBtn.height = (height - _decreaseBtn.height - _increaseBtn.height) * height / _targetDisplay.height;
				_thumbBtn.y = _scrollPos + _decreaseBtn.height;
			} else {
				DisplayUtils.removeDisplay(_thumbBtn);
			}
		}
		
		
		
		public function scrollTo(pos:int):void{
			updateThumb();
			if(_scrollPos == pos)return;
			var tempY:int = pos;
			var minY:int = 0;
			var maxY:int = height - _decreaseBtn.height - _increaseBtn.height - _thumbBtn.height;
			if(tempY > maxY){
				_scrollPos = maxY;
				_thumbBtn.y = maxY + _decreaseBtn.height;
				_targetDisplay.y = height - _targetDisplay.height + _originalPos;
				return;
			}
			if(tempY < minY){
				_scrollPos = minY;
				_thumbBtn.y = minY + _decreaseBtn.height;
				_targetDisplay.y =  + _originalPos;
				return;
			}
			if(_thumbBtn.y == tempY + _decreaseBtn.height)return;
			_thumbBtn.y = tempY + _decreaseBtn.height;
			var dis:int = tempY  - _scrollPos;
			var offset:int = dis * (_targetDisplay.height) / (height - _decreaseBtn.height - _increaseBtn.height);
			_targetDisplay.y -= offset
			_scrollPos = tempY;
		}
		
		private function __onThumbMouseDown(e:MouseEvent):void{
			updateThumb();
			_mouseY = _thumbBtn.mouseY;
			_isDraging = true;
			EventMgr.Instance.addEvent(StageManager.Instance.stage,[MouseEvent.MOUSE_MOVE],[__onThumbMove]);
			EventMgr.Instance.removeEvent(_thumbBtn, [MouseEvent.ROLL_OVER],[__onMouseUpHandler]);
			EventMgr.Instance.removeEvent(_decreaseBtn,[MouseEvent.ROLL_OUT],[__onMouseUpHandler]);
			EventMgr.Instance.removeEvent(_increaseBtn,[MouseEvent.ROLL_OUT],[__onMouseUpHandler]);
		}
		
		private function __onMouseUpHandler(e:MouseEvent):void{
			_btnTimer.reset();
			_btnTimer.stop();
			EventMgr.Instance.removeEvent(StageManager.Instance.stage,[MouseEvent.MOUSE_MOVE],[__onThumbMove]);
			EventMgr.Instance.addEvent(_thumbBtn, [MouseEvent.ROLL_OVER],[__onMouseUpHandler]);
			EventMgr.Instance.addEvent(_decreaseBtn,[MouseEvent.ROLL_OUT],[__onMouseUpHandler]);
			EventMgr.Instance.addEvent(_increaseBtn,[MouseEvent.ROLL_OUT],[__onMouseUpHandler]);
		}
		
		protected function __onThumbMove(e:MouseEvent):void{
			scrollTo(_scrollPos + _thumbBtn.mouseY - _mouseY);
			_mouseY = _thumbBtn.mouseY;
		}
		
		protected function __onMouseWheel(e:MouseEvent):void{
			var pos:Point = new Point(StageManager.Instance.stage.mouseX,StageManager.Instance.stage.mouseY);
			pos = globalToLocal(pos);
			if(pos.x > _wheelArea.x && pos.x < _wheelArea.width && pos.y > _wheelArea.y && pos.y < _wheelArea.height){
				scrollTo(_scrollPos + (e.delta < 0 ? _scrollUnit : -_scrollUnit));
			}
		}
		
		protected function __onBtnDownHandler(e:MouseEvent):void{
			e.stopImmediatePropagation();
			switch(e.target){
				case _decreaseBtn:
					_timerScrollUnit = -_scrollUnit;
					scrollTo(_scrollPos - _scrollUnit);
					break;
				case _increaseBtn:
					_timerScrollUnit = _scrollUnit;
					scrollTo(_scrollPos + _scrollUnit);
					break;
				case this:
					if(mouseY > _scrollPos + _decreaseBtn.height){
						_timerScrollUnit = _thumbBtn.height;
						scrollTo(_scrollPos + _thumbBtn.height);
					} else {
						_timerScrollUnit = -_thumbBtn.height;
						scrollTo(_scrollPos - _thumbBtn.height);
					}
					break;
				default:
					return;
			}
			_btnTimer.start();
		}
		
		private function __onBtnTimerTick(e:TimerEvent):void{
			if(_btnTimer.currentCount * _repeatTime > _delayTime){
				scrollTo(_scrollPos + _timerScrollUnit);
			}
		}
		
		override public function set enabled(value:Boolean):void{
			super.enabled = value;
			_increaseBtn.enabled = _decreaseBtn.enabled = value;
			if(!value){
				DisplayUtils.removeDisplay(_thumbBtn);
			} else {
				updateThumb();
			}
		}
		
		override public function dispose():void{
			super.dispose();
			if(_btnTimer){
				_btnTimer.stop();
				ObjectUtil.dispose(_btnTimer);_btnTimer=null;
			}
			EventMgr.Instance.removeEvent(StageManager.Instance.stage,[MouseEvent.MOUSE_UP,MouseEvent.MOUSE_WHEEL,MouseEvent.MOUSE_MOVE],[__onMouseUpHandler,__onMouseWheel,__onThumbMove]);
			ObjectUtil.dispose(_decreaseBtn);_decreaseBtn=null;
			ObjectUtil.dispose(_increaseBtn);_increaseBtn=null;
			ObjectUtil.dispose(_thumbBtn);_thumbBtn=null;
			ObjectUtil.dispose(_viewPort);_viewPort=null;
			ObjectUtil.dispose(_wheelArea);_wheelArea=null;
		}
	}
}